/* eslint-disable jsx-a11y/anchor-is-valid */
import { Popconfirm, Tooltip, Tree } from "antd";
import { PlusOutlined, FormOutlined, DeleteOutlined } from "@ant-design/icons";
import React, { useImperativeHandle, useState } from "react";
import { buildTreeData, loop, flatTreeData, rootNode } from "./utils";
import { DataNode } from "antd/lib/tree";
import "./AdvanceTree.css";

export interface AdvanceTreeNode {
  title: string;
  key: number | string;
  children: AdvanceTreeNode[];
  [propName: string]: any;
}

export interface AdvanceTreePlainNode {
  title: string;
  key: number | string;
  pid: number | string;
  [propName: string]: any;
}

export interface AdvanceTreeProps {
  data: AdvanceTreePlainNode[];
  onOpenAddModal: (pid: string | number) => void;
  onOpenModifyModal: (node: AdvanceTreeNode) => void;
}

export interface AdvanceTreeRef {
  /**
   * 新增节点
   */
  addNode: (node: AdvanceTreeNode, pid: string | number) => void;
  /**
   * 更新节点
   */
  updateNode: (node: AdvanceTreeNode) => void;
  /**
   * 获取数组化的数据
   */
  getData: () => AdvanceTreePlainNode[];
}

const AdvanceTree = React.forwardRef<AdvanceTreeRef, AdvanceTreeProps>(
  (props, ref) => {
    const [treeData, setTreeData] = useState<AdvanceTreeNode[]>(
      buildTreeData(rootNode, props.data)
    );

    useImperativeHandle(ref, () => {
      return {
        addNode(node: AdvanceTreeNode, pid: string | number) {
          const data = [...treeData];
          if (pid === rootNode) {
            data.push(node);
          } else {
            loop(data, pid, (item: any) => {
              item.children.push(node);
            });
          }

          setTreeData(data);
        },
        updateNode(node: AdvanceTreeNode) {
          const data = [...treeData];
          loop(data, node.key, (item: any, index: number, arr: any[]) => {
            arr.splice(index, 1, { ...item, ...node });
          });

          setTreeData(data);
        },
        getData() {
          return flatTreeData(treeData);
        },
      };
    });

    function onDrop(info: any) {
      const dropKey = info.node.key;
      const dragKey = info.dragNode.key;
      const dropPos = info.node.pos.split("-");
      const dropPosition =
        info.dropPosition - Number(dropPos[dropPos.length - 1]);
      const data = [...treeData];

      // Find dragObject
      let dragObj: any;
      loop(data, dragKey, (item: any, index: number, arr: any[]) => {
        arr.splice(index, 1);
        dragObj = item;
      });

      if (!info.dropToGap) {
        // Drop on the content
        loop(data, dropKey, (item: any) => {
          item.children = item.children || [];
          // where to insert 示例添加到头部，可以是随意位置
          item.children.unshift(dragObj);
        });
      } else if (
        (info.node.props.children || []).length > 0 && // Has children
        info.node.props.expanded && // Is expanded
        dropPosition === 1 // On the bottom gap
      ) {
        loop(data, dropKey, (item: any) => {
          item.children = item.children || [];
          // where to insert 示例添加到头部，可以是随意位置
          item.children.unshift(dragObj);
          // in previous version, we use item.children.push(dragObj) to insert the
          // item to the tail of the children
        });
      } else {
        let ar;
        let i;
        loop(data, dropKey, (item: any, index: number, arr: any[]) => {
          ar = arr;
          i = index;
        });
        if (dropPosition === -1) {
          // @ts-ignore
          ar.splice(i, 0, dragObj);
        } else {
          // @ts-ignore
          ar.splice(i + 1, 0, dragObj);
        }
      }

      setTreeData(data);
    }

    function onRemoveNode(key: number | string) {
      const data = [...treeData];
      let ar, i;
      loop(data, key, (item: any, index: number, arr: any[]) => {
        ar = arr;
        i = index;
      });

      // @ts-ignore
      ar.splice(i, 1);
      setTreeData(data);
    }

    function onAddNode(pid: string | number) {
      props.onOpenAddModal(pid);
    }

    function onModifyNode(node: AdvanceTreeNode) {
      props.onOpenModifyModal(node);
    }

    function titleRender(node: DataNode) {
      return (
        <div className="advance-tree__row">
          <span className="advance-tree__row__txt">{node.title}</span>
          <span className="advance-tree__row__tool">
            <Tooltip title="新增">
              <a
                onClick={() => {
                  onAddNode(node.key);
                }}
              >
                <PlusOutlined />
              </a>
            </Tooltip>
            <Tooltip title="编辑">
              <a
                onClick={() => {
                  onModifyNode(node as AdvanceTreeNode);
                }}
              >
                <FormOutlined />
              </a>
            </Tooltip>
            <Tooltip title="删除">
              <Popconfirm
                title="确认删除吗?"
                onConfirm={() => {
                  onRemoveNode(node.key);
                }}
                okText="Yes"
                cancelText="No"
              >
                <a>
                  <DeleteOutlined />
                </a>
              </Popconfirm>
            </Tooltip>
          </span>
        </div>
      );
    }

    return (
      <div className="advance-tree">
        <div className="advance-tree__body">
          <Tree
            className="draggable-tree"
            height={400}
            draggable
            blockNode
            showLine
            onDrop={onDrop}
            treeData={treeData}
            titleRender={titleRender}
          />
        </div>
      </div>
    );
  }
);

AdvanceTree.displayName = "AdvanceTree";

export default AdvanceTree;
